package com.yvan.periscope;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceStatValue;
import com.alibaba.druid.stat.JdbcSqlStatValue;
import com.alibaba.druid.support.http.stat.WebAppStatManager;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yvan.Conv;
import com.yvan.YvanUtil;
import com.yvan.es.EsStat;
import com.yvan.metric.Histogram;
import com.yvan.platform.JsonWapper;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import redis.clients.jedis.RedisStat;

import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.Map;

@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON, proxyMode = ScopedProxyMode.NO)
public class CollectorService implements InitializingBean {

    private static final Logger LOG_SUMMARY = LoggerFactory.getLogger("PER.SUMMARY");
    private static final Logger LOG_URI = LoggerFactory.getLogger("PER.URI");
    private static final Logger LOG_SQL = LoggerFactory.getLogger("PER.SQL");

    @Autowired
    private ApplicationContext applicationContext;

    private DruidDataSource dataSource;
    private JsonWapper lastCollect;

    @Value("${spring.application.name}")
    private String app;
    private final String server;

    public CollectorService() {
        server = ManagementFactory.getRuntimeMXBean().getName().split("\\@")[1];
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        try {
            this.dataSource = applicationContext.getBean(DruidDataSource.class);
        } catch (NoSuchBeanDefinitionException e) {
            this.dataSource = null;
        }
    }

    public synchronized void collect() {
        final DateTime now = DateTime.now();
        JsonWapper summary = new JsonWapper()
                .set("@timestamp", now.getMillis())
                .set("app", app)
                .set("server", server);

        List<Map<String, Object>> sqlList = getJdbcMapAndReset(summary);
        getRedisMapAndReset(summary);
        getEsMapAndReset(summary);
        List<Map<String, Object>> uriList = getUriMapAndReset(summary);
        lastCollect = summary;
        LOG_SUMMARY.info(YvanUtil.toJson(summary.getInnerMap()));

        for (Map<String, Object> entry : sqlList) {
            entry.put("@timestamp", now.getMillis());
            entry.put("app", app);
            entry.put("server", server);
            LOG_SQL.info(YvanUtil.toJson(entry));
        }

        for (Map<String, Object> entry : uriList) {
            entry.put("@timestamp", now.getMillis());
            entry.put("app", app);
            entry.put("server", server);
            LOG_URI.info(YvanUtil.toJson(entry));
        }
        //LOGGER.info("collect");
        //WebAppStatManager.getInstance().resetStat();
        //dataSource.getDataSourceStat().reset();
        //dataSource.getDataSourceStat().getStatementStat().reset();
        //dataSource.getDataSourceStat().getConnectionStat().reset();
    }

    private void getRedisMapAndReset(JsonWapper jw) {
        if (RedisStat.getExecuteCount() <= 0) {
            return;
        }

        jw.set("rdsCount", RedisStat.getExecuteCount());
        jw.set("rdsCostMax", RedisStat.getMaxCost());
        jw.set("rdsCostMaxUri", RedisStat.getMaxCostUri());
        jw.set("rdsResMax", RedisStat.getMaxResBytes());
        jw.set("rdsCostTotal", RedisStat.getTotalCost());
        jw.set("rdsResTotal", RedisStat.getResBytes());

        long[] cc = RedisStat.getExecuteHistogram();
        Histogram.writeToMap(jw, "rds_c", cc);

        cc = RedisStat.getResSizeHistogram();
        Histogram.writeToMap(jw, "rds_s", cc);

        jw.set("method_count", RedisStat.methodCount());

        RedisStat.resetStat();
    }

    private void getEsMapAndReset(JsonWapper jw) {
        if (EsStat.getExecuteCount() <= 0) {
            return;
        }

        jw.set("esCount", EsStat.getExecuteCount());
        jw.set("esCostMax", EsStat.getMaxCost());
        jw.set("esResMax", EsStat.getMaxResBytes());
        jw.set("esReqMax", EsStat.getMaxReqBytes());
        jw.set("esCostMaxUri", EsStat.getMaxCostUri());
        jw.set("esResMaxUri", EsStat.getMaxResBytesUri());
        jw.set("esReqMaxUri", EsStat.getMaxReqBytesUri());
        jw.set("esCostTotal", EsStat.getTotalCost());
        jw.set("esResTotal", EsStat.getResBytes());
        jw.set("esReqTotal", EsStat.getReqBytes());

        long[] cc = EsStat.getExecuteHistogram();
        Histogram.writeToMap(jw, "es_c", cc);

        cc = EsStat.getReqSizeHistogram();
        Histogram.writeToMap(jw, "es_r", cc);

        cc = EsStat.getResSizeHistogram();
        Histogram.writeToMap(jw, "es_s", cc);

        EsStat.resetStat();
    }

    public JsonWapper current() {
        return lastCollect;
    }

    private List<Map<String, Object>> getUriMapAndReset(JsonWapper jw) {
        List<Map<String, Object>> webs = WebAppStatManager.getInstance().getWebAppStatData();
        List<Map<String, Object>> uriList = Lists.newArrayList();
        if (webs == null) {
            return uriList;
        }
        for (Map<String, Object> map : webs) {
            jw.set("concurrentMax", Math.max(Conv.NL(map.get("ConcurrentMax")), jw.asLong("concurrentMax")));
            jw.set("requestCount", Conv.NL(map.get("RequestCount")) + jw.asLong("requestCount"));
            if (jw.get("requestCostHistogram") == null) {
                jw.set("requestCostHistogram", map.get("RequestCostHistogram"));
            } else {
                jw.set("requestCostHistogram",
                        Histogram.mergeArray(jw.get("requestCostHistogram"), map.get("RequestCostHistogram"))
                );
            }
            jw.set("sessionCount", Conv.NL(map.get("SessionCount")) + jw.asLong("sessionCount"));
            jw.set("jdbcExecuteTimeMillis", Conv.NL(map.get("JdbcExecuteTimeMillis")) + jw.asLong("jdbcExecuteTimeMillis"));
            jw.set("jdbcFetchRowCount", Conv.NL(map.get("JdbcFetchRowCount")) + jw.asLong("jdbcFetchRowCount"));
            jw.set("jdbcUpdateCount", Conv.NL(map.get("JdbcUpdateCount")) + jw.asLong("jdbcUpdateCount"));

            jw.set("osMacOSXCount", Conv.NL(map.get("OSMacOSXCount")) + jw.asLong("osMacOSXCount"));
            jw.set("osWindowsCount", Conv.NL(map.get("OSWindowsCount")) + jw.asLong("osWindowsCount"));
            jw.set("osLinuxCount", Conv.NL(map.get("OSLinuxCount")) + jw.asLong("osLinuxCount"));
            jw.set("osSymbianCount", Conv.NL(map.get("OSSymbianCount")) + jw.asLong("osSymbianCount"));
            jw.set("osFreeBSDCount", Conv.NL(map.get("OSFreeBSDCount")) + jw.asLong("osFreeBSDCount"));
            jw.set("osOpenBSDCount", Conv.NL(map.get("OSOpenBSDCount")) + jw.asLong("osOpenBSDCount"));
            jw.set("osAndroidCount", Conv.NL(map.get("OSAndroidCount")) + jw.asLong("osAndroidCount"));
            jw.set("osWindows98Count", Conv.NL(map.get("OSWindows98Count")) + jw.asLong("osWindows98Count"));
            jw.set("osWindowsXPCount", Conv.NL(map.get("OSWindowsXPCount")) + jw.asLong("osWindowsXPCount"));
            jw.set("osWindows2000Count", Conv.NL(map.get("OSWindows2000Count")) + jw.asLong("osWindows2000Count"));
            jw.set("osWindowsVistaCount", Conv.NL(map.get("OSWindowsVistaCount")) + jw.asLong("osWindowsVistaCount"));
            jw.set("osWindows7Count", Conv.NL(map.get("OSWindows7Count")) + jw.asLong("osWindows7Count"));
            jw.set("osWindows8Count", Conv.NL(map.get("OSWindows8Count")) + jw.asLong("osWindows8Count"));
            jw.set("osAndroid15Count", Conv.NL(map.get("OSAndroid15Count")) + jw.asLong("osAndroid15Count"));
            jw.set("osAndroid16Count", Conv.NL(map.get("OSAndroid16Count")) + jw.asLong("osAndroid16Count"));
            jw.set("osAndroid20Count", Conv.NL(map.get("OSAndroid20Count")) + jw.asLong("osAndroid20Count"));
            jw.set("osAndroid21Count", Conv.NL(map.get("OSAndroid21Count")) + jw.asLong("osAndroid21Count"));
            jw.set("osAndroid22Count", Conv.NL(map.get("OSAndroid22Count")) + jw.asLong("osAndroid22Count"));
            jw.set("osAndroid23Count", Conv.NL(map.get("OSAndroid23Count")) + jw.asLong("osAndroid23Count"));
            jw.set("osAndroid30Count", Conv.NL(map.get("OSAndroid30Count")) + jw.asLong("osAndroid30Count"));
            jw.set("osAndroid31Count", Conv.NL(map.get("OSAndroid31Count")) + jw.asLong("osAndroid31Count"));
            jw.set("osAndroid32Count", Conv.NL(map.get("OSAndroid32Count")) + jw.asLong("osAndroid32Count"));
            jw.set("osAndroid40Count", Conv.NL(map.get("OSAndroid40Count")) + jw.asLong("osAndroid40Count"));
            jw.set("osAndroid41Count", Conv.NL(map.get("OSAndroid41Count")) + jw.asLong("osAndroid41Count"));
            jw.set("osAndroid42Count", Conv.NL(map.get("OSAndroid42Count")) + jw.asLong("osAndroid42Count"));
            jw.set("osAndroid43Count", Conv.NL(map.get("OSAndroid43Count")) + jw.asLong("osAndroid43Count"));
            jw.set("osLinuxUbuntuCount", Conv.NL(map.get("OSLinuxUbuntuCount")) + jw.asLong("osLinuxUbuntuCount"));
            jw.set("browserIECount", Conv.NL(map.get("BrowserIECount")) + jw.asLong("browserIECount"));
            jw.set("browserFirefoxCount", Conv.NL(map.get("BrowserFirefoxCount")) + jw.asLong("browserFirefoxCount"));
            jw.set("browserChromeCount", Conv.NL(map.get("BrowserChromeCount")) + jw.asLong("browserChromeCount"));
            jw.set("browserSafariCount", Conv.NL(map.get("BrowserSafariCount")) + jw.asLong("browserSafariCount"));
            jw.set("browserOperaCount", Conv.NL(map.get("BrowserOperaCount")) + jw.asLong("browserOperaCount"));
            jw.set("browserIE5Count", Conv.NL(map.get("BrowserIE5Count")) + jw.asLong("browserIE5Count"));
            jw.set("browserIE6Count", Conv.NL(map.get("BrowserIE6Count")) + jw.asLong("browserIE6Count"));
            jw.set("browserIE7Count", Conv.NL(map.get("BrowserIE7Count")) + jw.asLong("browserIE7Count"));
            jw.set("browserIE8Count", Conv.NL(map.get("BrowserIE8Count")) + jw.asLong("browserIE8Count"));
            jw.set("browserIE9Count", Conv.NL(map.get("BrowserIE9Count")) + jw.asLong("browserIE9Count"));
            jw.set("browserIE10Count", Conv.NL(map.get("BrowserIE10Count")) + jw.asLong("browserIE10Count"));
            jw.set("browser360SECount", Conv.NL(map.get("Browser360SECount")) + jw.asLong("browser360SECount"));
            jw.set("deviceAndroidCount", Conv.NL(map.get("DeviceAndroidCount")) + jw.asLong("deviceAndroidCount"));
            jw.set("deviceIpadCount", Conv.NL(map.get("DeviceIpadCount")) + jw.asLong("deviceIpadCount"));
            jw.set("deviceIphoneCount", Conv.NL(map.get("DeviceIphoneCount")) + jw.asLong("deviceIphoneCount"));
            jw.set("deviceWindowsPhoneCount", Conv.NL(map.get("DeviceWindowsPhoneCount")) + jw.asLong("deviceWindowsPhoneCount"));
            jw.set("botCount", Conv.NL(map.get("BotCount")) + jw.asLong("botCount"));
            jw.set("botBaiduCount", Conv.NL(map.get("BotBaiduCount")) + jw.asLong("botBaiduCount"));
            jw.set("botYoudaoCount", Conv.NL(map.get("BotYoudaoCount")) + jw.asLong("botYoudaoCount"));
            jw.set("botGoogleCount", Conv.NL(map.get("BotGoogleCount")) + jw.asLong("botGoogleCount"));
            jw.set("botMsnCount", Conv.NL(map.get("BotMsnCount")) + jw.asLong("botMsnCount"));
            jw.set("botBingCount", Conv.NL(map.get("BotBingCount")) + jw.asLong("botBingCount"));
            jw.set("botSosoCount", Conv.NL(map.get("BotSosoCount")) + jw.asLong("botSosoCount"));
            jw.set("botSogouCount", Conv.NL(map.get("BotSogouCount")) + jw.asLong("botSogouCount"));
            jw.set("botYahooCount", Conv.NL(map.get("BotYahooCount")) + jw.asLong("botYahooCount"));
        }

        if (jw.asLong("concurrentMax") <= 0) jw.remove("concurrentMax");
        if (jw.asLong("requestCount") <= 0) jw.remove("requestCount");

        long[] cc1 = (long[]) jw.get("requestCostHistogram");
        Histogram.writeToMap(jw, "cost", cc1);
        jw.remove("requestCostHistogram");

        if (jw.asLong("sessionCount") <= 0) jw.remove("sessionCount");
        if (jw.asLong("jdbcExecuteTimeMillis") <= 0) jw.remove("jdbcExecuteTimeMillis");
        if (jw.asLong("jdbcFetchRowCount") <= 0) jw.remove("jdbcFetchRowCount");
        if (jw.asLong("jdbcUpdateCount") <= 0) jw.remove("jdbcUpdateCount");
        if (jw.asLong("osMacOSXCount") <= 0) jw.remove("osMacOSXCount");
        if (jw.asLong("osWindowsCount") <= 0) jw.remove("osWindowsCount");
        if (jw.asLong("osLinuxCount") <= 0) jw.remove("osLinuxCount");
        if (jw.asLong("osSymbianCount") <= 0) jw.remove("osSymbianCount");
        if (jw.asLong("osFreeBSDCount") <= 0) jw.remove("osFreeBSDCount");
        if (jw.asLong("osOpenBSDCount") <= 0) jw.remove("osOpenBSDCount");
        if (jw.asLong("osAndroidCount") <= 0) jw.remove("osAndroidCount");
        if (jw.asLong("osWindows98Count") <= 0) jw.remove("osWindows98Count");
        if (jw.asLong("osWindowsXPCount") <= 0) jw.remove("osWindowsXPCount");
        if (jw.asLong("osWindows2000Count") <= 0) jw.remove("osWindows2000Count");
        if (jw.asLong("osWindowsVistaCount") <= 0) jw.remove("osWindowsVistaCount");
        if (jw.asLong("osWindows7Count") <= 0) jw.remove("osWindows7Count");
        if (jw.asLong("osWindows8Count") <= 0) jw.remove("osWindows8Count");
        if (jw.asLong("osAndroid15Count") <= 0) jw.remove("osAndroid15Count");
        if (jw.asLong("osAndroid16Count") <= 0) jw.remove("osAndroid16Count");
        if (jw.asLong("osAndroid20Count") <= 0) jw.remove("osAndroid20Count");
        if (jw.asLong("osAndroid21Count") <= 0) jw.remove("osAndroid21Count");
        if (jw.asLong("osAndroid22Count") <= 0) jw.remove("osAndroid22Count");
        if (jw.asLong("osAndroid23Count") <= 0) jw.remove("osAndroid23Count");
        if (jw.asLong("osAndroid30Count") <= 0) jw.remove("osAndroid30Count");
        if (jw.asLong("osAndroid31Count") <= 0) jw.remove("osAndroid31Count");
        if (jw.asLong("osAndroid32Count") <= 0) jw.remove("osAndroid32Count");
        if (jw.asLong("osAndroid40Count") <= 0) jw.remove("osAndroid40Count");
        if (jw.asLong("osAndroid41Count") <= 0) jw.remove("osAndroid41Count");
        if (jw.asLong("osAndroid42Count") <= 0) jw.remove("osAndroid42Count");
        if (jw.asLong("osAndroid43Count") <= 0) jw.remove("osAndroid43Count");
        if (jw.asLong("osLinuxUbuntuCount") <= 0) jw.remove("osLinuxUbuntuCount");
        if (jw.asLong("browserIECount") <= 0) jw.remove("browserIECount");
        if (jw.asLong("browserFirefoxCount") <= 0) jw.remove("browserFirefoxCount");
        if (jw.asLong("browserChromeCount") <= 0) jw.remove("browserChromeCount");
        if (jw.asLong("browserSafariCount") <= 0) jw.remove("browserSafariCount");
        if (jw.asLong("browserOperaCount") <= 0) jw.remove("browserOperaCount");
        if (jw.asLong("browserIE5Count") <= 0) jw.remove("browserIE5Count");
        if (jw.asLong("browserIE6Count") <= 0) jw.remove("browserIE6Count");
        if (jw.asLong("browserIE7Count") <= 0) jw.remove("browserIE7Count");
        if (jw.asLong("browserIE8Count") <= 0) jw.remove("browserIE8Count");
        if (jw.asLong("browserIE9Count") <= 0) jw.remove("browserIE9Count");
        if (jw.asLong("browserIE10Count") <= 0) jw.remove("browserIE10Count");
        if (jw.asLong("browser360SECount") <= 0) jw.remove("browser360SECount");
        if (jw.asLong("deviceAndroidCount") <= 0) jw.remove("deviceAndroidCount");
        if (jw.asLong("deviceIpadCount") <= 0) jw.remove("deviceIpadCount");
        if (jw.asLong("deviceIphoneCount") <= 0) jw.remove("deviceIphoneCount");
        if (jw.asLong("deviceWindowsPhoneCount") <= 0) jw.remove("deviceWindowsPhoneCount");
        if (jw.asLong("botCount") <= 0) jw.remove("botCount");
        if (jw.asLong("botBaiduCount") <= 0) jw.remove("botBaiduCount");
        if (jw.asLong("botYoudaoCount") <= 0) jw.remove("botYoudaoCount");
        if (jw.asLong("botGoogleCount") <= 0) jw.remove("botGoogleCount");
        if (jw.asLong("botMsnCount") <= 0) jw.remove("botMsnCount");
        if (jw.asLong("botBingCount") <= 0) jw.remove("botBingCount");
        if (jw.asLong("botSosoCount") <= 0) jw.remove("botSosoCount");
        if (jw.asLong("botSogouCount") <= 0) jw.remove("botSogouCount");
        if (jw.asLong("botYahooCount") <= 0) jw.remove("botYahooCount");


        List<Map<String, Object>> data = WebAppStatManager.getInstance().getURIStatData();
        if (data.size() > 0) {
            for (Map<String, Object> entry : data) {
                Map<String, Object> item = Maps.newLinkedHashMap();
                item.put("uri", entry.get("URI"));

                if (Conv.NL(entry.get("ConcurrentMax")) > 0)
                    item.put("concurrentMax", entry.get("ConcurrentMax"));

                if (Conv.NL(entry.get("RequestCount")) > 0)
                    item.put("requestCount", entry.get("RequestCount"));

                if (Conv.NL(entry.get("RequestTimeMillis")) > 0)
                    item.put("requestTimeMillis", entry.get("RequestTimeMillis"));

                if (Conv.NL(entry.get("ErrorCount")) > 0)
                    item.put("errorCount", entry.get("ErrorCount"));

                if (Conv.NL(entry.get("JdbcCommitCount")) > 0)
                    item.put("jdbcCommitCount", entry.get("JdbcCommitCount"));

                if (Conv.NL(entry.get("JdbcRollbackCount")) > 0)
                    item.put("jdbcRollbackCount", entry.get("JdbcRollbackCount"));

                if (Conv.NL(entry.get("JdbcExecuteCount")) > 0)
                    item.put("jdbcExecuteCount", entry.get("JdbcExecuteCount"));

                if (Conv.NL(entry.get("JdbcExecuteErrorCount")) > 0)
                    item.put("jdbcExecuteErrorCount", entry.get("JdbcExecuteErrorCount"));

                if (Conv.NL(entry.get("JdbcExecutePeak")) > 0)
                    item.put("jdbcExecutePeak", entry.get("JdbcExecutePeak"));

                if (Conv.NL(entry.get("JdbcExecuteTimeMillis")) > 0)
                    item.put("jdbcExecuteTimeMillis", entry.get("JdbcExecuteTimeMillis"));

                if (Conv.NL(entry.get("JdbcFetchRowCount")) > 0)
                    item.put("jdbcFetchRowCount", entry.get("JdbcFetchRowCount"));

                if (Conv.NL(entry.get("JdbcFetchRowPeak")) > 0)
                    item.put("jdbcFetchRowPeak", entry.get("JdbcFetchRowPeak"));

                if (Conv.NL(entry.get("JdbcUpdateCount")) > 0)
                    item.put("jdbcUpdateCount", entry.get("JdbcUpdateCount"));

                if (Conv.NL(entry.get("JdbcUpdatePeak")) > 0)
                    item.put("jdbcUpdatePeak", entry.get("JdbcUpdatePeak"));

                if (Conv.NL(entry.get("JdbcPoolConnectionOpenCount")) > 0)
                    item.put("jdbcPoolConnectionOpenCount", entry.get("JdbcPoolConnectionOpenCount"));

                if (Conv.NL(entry.get("JdbcPoolConnectionCloseCount")) > 0)
                    item.put("jdbcPoolConnectionCloseCount", entry.get("JdbcPoolConnectionCloseCount"));

                if (Conv.NL(entry.get("JdbcResultSetOpenCount")) > 0)
                    item.put("jdbcResultSetOpenCount", entry.get("JdbcResultSetOpenCount"));

                if (Conv.NL(entry.get("JdbcResultSetCloseCount")) > 0)
                    item.put("jdbcResultSetCloseCount", entry.get("JdbcResultSetCloseCount"));

                long[] cc = (long[]) entry.get("Histogram");
                Histogram.writeToMap(item, "cost", cc);

                if (Conv.NL(entry.get("RequestTimeMillisMax")) > 0)
                    item.put("requestTimeMillisMax", entry.get("RequestTimeMillisMax"));

                if (Conv.NL(entry.get("RequestTimeMillisMaxOccurTime")) > 0)
                    item.put("requestTimeMillisMaxOccurTime", entry.get("RequestTimeMillisMaxOccurTime"));


                uriList.add(item);
            }
        }
        WebAppStatManager.getInstance().resetStat();
        return uriList;
    }

    private List<Map<String, Object>> getJdbcMapAndReset(JsonWapper jw) {
        List<Map<String, Object>> sqlList = Lists.newArrayList();
        if (dataSource == null) {
            return sqlList;
        }

        //获取jdbc状态
        DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset();
        if (statValue.getActiveCount() > 0) {
            jw.set("jdbcActiveCount", statValue.getActiveCount());
        }

        if (statValue.getActivePeak() > 0) {
            jw.set("jdbcActivePeak", statValue.getActivePeak());
            jw.set("jdbcActivePeakTime", statValue.getActivePeakTime());
        }
        if (statValue.getPoolingCount() > 0) {
            jw.set("jdbcPoolingCount", statValue.getPoolingCount());
        }
        if (statValue.getPoolingPeak() > 0) {
            jw.set("jdbcPoolingPeak", statValue.getPoolingPeak());
        }
        if (statValue.getConnectCount() > 0) {
            jw.set("jdbcConnectCount", statValue.getConnectCount());

            //jw.set("connectionHoldTimeHistogram", rtrim(statValue.getConnectionHoldTimeHistogram()));
            long[] cc = statValue.getConnectionHoldTimeHistogram();
            Histogram.writeToMap(jw, "txh", cc);
        }
        if (statValue.getCloseCount() > 0) {
            jw.set("jdbcCloseCount", statValue.getCloseCount());
        }

        if (statValue.getWaitThreadCount() > 0) {
            jw.set("waitThreadCount", statValue.getWaitThreadCount());
        }

        if (statValue.getNotEmptyWaitCount() > 0) {
            jw.set("notEmptyWaitCount", statValue.getNotEmptyWaitCount());
        }

        if (statValue.getNotEmptyWaitMillis() > 0) {
            jw.set("notEmptyWaitMillis", statValue.getNotEmptyWaitMillis());
        }

        if (statValue.getLogicConnectErrorCount() > 0) {
            jw.set("logicConnectErrorCount", statValue.getLogicConnectErrorCount());
        }

        if (statValue.getPhysicalConnectCount() > 0) {
            jw.set("physicalConnectCount", statValue.getPhysicalConnectCount());
        }

        if (statValue.getPhysicalCloseCount() > 0) {
            jw.set("physicalCloseCount", statValue.getPhysicalCloseCount());
        }

        if (statValue.getPhysicalConnectErrorCount() > 0) {
            jw.set("physicalConnectErrorCount", statValue.getPhysicalConnectErrorCount());
        }

        if (statValue.getErrorCount() > 0) {
            jw.set("jdbcErrorCount", statValue.getErrorCount());
        }

        if (statValue.getCommitCount() > 0) {
            jw.set("jdbcCommitCount", statValue.getCommitCount());
        }

        if (statValue.getRollbackCount() > 0) {
            jw.set("jdbcRollbackCount", statValue.getRollbackCount());
        }

        if (statValue.getExecuteCount() > 0) {
            jw.set("jdbcExecuteCount", statValue.getExecuteCount());
        }

        if (statValue.getPstmtCacheHitCount() > 0) {
            jw.set("pstmtCacheHitCount", statValue.getPstmtCacheHitCount());
        }

        if (statValue.getPstmtCacheMissCount() > 0) {
            jw.set("pstmtCacheMissCount", statValue.getPstmtCacheMissCount());
        }

        if (statValue.getStartTransactionCount() > 0) {
            jw.set("startTransactionCount", statValue.getStartTransactionCount());

            //jw.set("transactionHistogram", rtrim(statValue.getTransactionHistogram()));
            long[] cc = statValue.getTransactionHistogram();
            Histogram.writeToMap(jw, "txn", cc);
        }

        if (statValue.getClobOpenCount() > 0) {
            jw.set("clobOpenCount", statValue.getClobOpenCount());
        }

        if (statValue.getBlobOpenCount() > 0) {
            jw.set("blobOpenCount", statValue.getBlobOpenCount());
        }

        if (statValue.getSqlSkipCount() > 0) {
            jw.set("sqlSkipCount", statValue.getSqlSkipCount());
        }

        if (statValue.getKeepAliveCheckCount() > 0) {
            jw.set("keepAliveCheckCount", statValue.getKeepAliveCheckCount());
        }

        for (JdbcSqlStatValue sqlStat : statValue.getSqlList()) {
            Map<String, Object> sqlStatMap = Maps.newLinkedHashMap();
            sqlStatMap.put("sql", sqlStat.getSql());

            if (sqlStat.getExecuteCount() > 0) {
                sqlStatMap.put("executeCount", sqlStat.getExecuteCount());
                sqlStatMap.put("executeMillisMax", sqlStat.getExecuteMillisMax());
                sqlStatMap.put("executeMillisTotal", sqlStat.getExecuteMillisTotal());

                //sqlStatMap.put("executeHistogram", rtrim(sqlStat.getExecuteHistogram()));
                long[] cc = sqlStat.getExecuteHistogram();
                Histogram.writeToMap(sqlStatMap, "cost", cc);

                //sqlStatMap.put("executeAndResultHoldHistogram", rtrim(sqlStat.getExecuteAndResultHoldHistogram()));
                cc = sqlStat.getExecuteAndResultHoldHistogram();
                Histogram.writeToMap(sqlStatMap, "hold", cc);
            }

            long executeErrorCount = sqlStat.getExecuteErrorCount();
            if (executeErrorCount > 0) {
                sqlStatMap.put("executeErrorCount", executeErrorCount);
            }

            int concurrentMax = sqlStat.getConcurrentMax();
            if (concurrentMax > 0) {
                sqlStatMap.put("concurrentMax", concurrentMax);
            }

            if (sqlStat.getFetchRowCount() > 0) {
                sqlStatMap.put("fetchRowCount", sqlStat.getFetchRowCount());
                sqlStatMap.put("fetchRowCountMax", sqlStat.getFetchRowCountMax());
                //sqlStatMap.put("fetchRowHistogram", rtrim(sqlStat.getFetchRowHistogram()));
                long[] cc = sqlStat.getFetchRowHistogram();
                Histogram.writeToMap(sqlStatMap, "select", cc);
            }

            if (sqlStat.getUpdateCount() > 0) {
                sqlStatMap.put("updateCount", sqlStat.getUpdateCount());
                sqlStatMap.put("updateCountMax", sqlStat.getUpdateCountMax());
                //sqlStatMap.put("updateHistogram", rtrim(sqlStat.getUpdateHistogram()));
                long[] cc = sqlStat.getUpdateHistogram();
                Histogram.writeToMap(sqlStatMap, "update", cc);
            }

            if (sqlStat.getClobOpenCount() > 0) {
                sqlStatMap.put("clobOpenCount", sqlStat.getClobOpenCount());
            }

            if (sqlStat.getBlobOpenCount() > 0) {
                sqlStatMap.put("blobOpenCount", sqlStat.getBlobOpenCount());
            }

            sqlList.add(sqlStatMap);
        }
        return sqlList;
    }
}
